/*
 * @(#)DefaultObjectNormalizer.java $version 2010. 8. 11
 *
 * Copyright 2007-2010 NHN Corp. All rights Reserved. 
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.nhncorp.usf.core.normalizer;

import java.io.InputStream;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtils;

import com.nhncorp.usf.core.invoker.InvocationFuture;
  
/**
 * The Class DefaultObjectNormalizer.
 *
 * @author MiddleWare Platform Development Team
 */
public class DefaultObjectNormalizer implements ObjectNormalizer {

    /**
     * Instantiates a new default object normalizer.
     */
    public DefaultObjectNormalizer() {
        super();
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public Object normalize(Object object) {
        if (object == null) {
            return null;
        }

        if (object instanceof String || object instanceof Number || object instanceof Boolean
                || object instanceof Character || object instanceof Date
                || object instanceof Calendar || object instanceof byte[]
                || object instanceof InputStream || object instanceof ByteBuffer
                || object instanceof InvocationFuture) {
            return object;
        }

        if (object instanceof Map) {
            return normalizeMap((Map<Object, Object>) object);
        }

        if (object instanceof Collection) {
            List<Object> answer = new ArrayList<Object>();

            for (Object entry : (Collection<?>) object) {
                answer.add(normalize(entry));
            }

            return answer;
        }

        if (object.getClass().isArray()) {
            List<Object> answer = new ArrayList<Object>();
            int len = Array.getLength(object);

            for (int i = 0; i < len; i++) {
                answer.add(normalize(Array.get(object, i)));
            }

            return answer;
        }

        // FIXME: Property
        try {
            Object described = PropertyUtils.describe(object);
            return normalizeMap((Map<Object, Object>) described);
        } catch (Exception e) {
            throw new ObjectNormalizerException("Failed to convert a Java object into a Map.", e);
        }

        // return normalizeMap((Map<Object, Object>) object);
    }

    /**
     * Normalize map.
     *
     * @param map the m
     * @return the map< object, object>
     */
    private Map<Object, Object> normalizeMap(Map<Object, Object> map) {
        Map<Object, Object> normalized = new LinkedHashMap<Object, Object>();

        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            Object value = entry.getValue();

            if (value != null && !"class".equals(entry.getKey())) {
                normalized.put(entry.getKey(), normalize(value));
            }
        }

        return normalized;
	}
}